#pragma once
#include "../Ode.h"

namespace Skill
{
	namespace Ode
	{		
		namespace Geometries
		{
			ref class DGeometry;
			ref class DTriMesh;
		}
	}
}

using namespace Skill::Ode::Geometries;

namespace Skill
{
	namespace Ode
	{		
		ref class DVector4;
		ref class DVector3;
		ref class DMatrix3;

		public ref class DMass : DIUnmanagedPointer
		{
			INTERNAL_CLASS_DECLARATION_NO_FINALIZE(DMass,dMass);
		public:
			UNMANAGEDPOINTER_DECLARATION();

			VALUE_PROP_DECLARATION_GETSET(dReal,Mass);
			REF_PROP_DECLARATION_GETSET(DVector4,Center);
			REF_PROP_DECLARATION_GETSET(DMatrix3,InteriaTensor);

			!DMass()
			{
				if(_Free && _This)
					delete _This;
				_This = nullptr;
				_Free = false;
				_Disposed = true;
			}
			DMass()
			{
				_SetPointer(new dMass(),true);
			}

			/// <summary>
			/// Check if a mass structure has valid value.
			/// The function check if the mass and innertia matrix are positive definits 
			/// </summary>
			/// <param name = "m"> A mass structure to check </param>
			/// <returns> true if both codition are met </returns>
			static bool Check(DMass^ m);

			void SetZero();
			static VALUE_PROP_DECLARATION_GET(DMass^,Zero);

			void SetParameters(dReal themass,
				dReal cgx, dReal cgy, dReal cgz,
				dReal I11, dReal I22, dReal I33,
				dReal I12, dReal I13, dReal I23);
			static DMass^ FromParameters(dReal themass,
				dReal cgx, dReal cgy, dReal cgz,
				dReal I11, dReal I22, dReal I33,
				dReal I12, dReal I13, dReal I23);

			void SetSphere(dReal density, dReal radius);
			static DMass^ FromSphere(dReal density, dReal radius);

			void SetSphereTotal(dReal total_mass, dReal radius);
			static DMass^ FromSphereTotal(dReal total_mass, dReal radius);

			void SetCapsule(dReal density, int direction, dReal radius, dReal length);
			static DMass^ FromCapsule(dReal density, int direction, dReal radius, dReal length);

			void SetCapsuleTotal(dReal total_mass, int direction, dReal radius, dReal length);
			static DMass^ FromCapsuleTotal(dReal total_mass, int direction, dReal radius, dReal length);

			void SetCylinder(dReal density, int direction, dReal radius, dReal length);
			static DMass^ FromCylinder(dReal density, int direction, dReal radius, dReal length);

			void SetCylinderTotal(dReal total_mass, int direction, dReal radius, dReal length);
			static DMass^ FromCylinderTotal(dReal total_mass, int direction, dReal radius, dReal length);


			void SetCappedCylinder(dReal density, int direction, dReal radius, dReal length);
			static DMass^ FromCappedCylinder(dReal density, int direction, dReal radius, dReal length);

			void SetCappedCylinderTotal(dReal total_mass, int direction, dReal radius, dReal length);
			static DMass^ FromCappedCylinderTotal(dReal total_mass, int direction, dReal radius, dReal length);


			void SetBox(dReal density, dReal lx, dReal ly, dReal lz);
			static DMass^ FromBox(dReal density, dReal lx, dReal ly, dReal lz);

			void SetBox(dReal density, DVector3^ l);
			static DMass^ FromBox(dReal density, DVector3^ l);

			void SetBoxTotal(dReal total_mass, dReal lx, dReal ly, dReal lz);
			static DMass^ FromBoxTotal(dReal total_mass, dReal lx, dReal ly, dReal lz);

			void SetBoxTotal(dReal total_mass, DVector3^ l);
			static DMass^ FromBoxTotal(dReal total_mass, DVector3^ l);

			void SetTrimesh(dReal density, DTriMesh^ mesh);
			static DMass^ FromTrimesh(dReal density, DTriMesh^ mesh);

			void SetTrimeshTotal(dReal total_mass, DTriMesh^ mesh);
			static DMass^ FromTrimeshTotal(dReal total_mass, DTriMesh^ mesh);

			void Adjust(dReal newmass);

			void Translate(dReal x, dReal y, dReal z);
			void Translate(DVector3^ t);
			void Rotate(DMatrix3^ r);
			void Add(DMass^ b);
		};		
	}
}